

#ifndef __COMM_TIME_H__
#define __COMM_TIME_H__
#include "comm/comm_data_type.h"

#include <string.h>
#include <atomic>
#include <mutex>
#include <list>

using namespace std;

typedef struct {
    unsigned short year;
    unsigned char  month;
    unsigned char  day;

    unsigned char  hour;
    unsigned char  min;
    unsigned char  sec;
} ST_TIME_STRU;

INT32 Comm_InitTimer(int runFrequency);
void  Comm_UptTimer(void);

/**************************************************************************************
功能描述: 获取系统时间，避免频繁调用
修改记录:
**************************************************************************************/
double Comm_GetTimeSecRos(void);
double Comm_GetTimeSec(void);
void   Comm_GetTime(ST_TIME_STRU &stTime);
const char *Comm_GetTimeStr(void);

class UPT_BASE_C
{
public:
    virtual void Upt(void) = 0;
    virtual ~UPT_BASE_C(){}
};

class UPT_MNG_C
{
public:
    UPT_MNG_C(void)
    {
    }

    void Add(UPT_BASE_C *pobjUpt);
    void Rmv(UPT_BASE_C *pobjUpt);
    void UptAll(void);
private:
    mutex              objMutex_;
    list<UPT_BASE_C *> lstUpt_;
};

class TIMER_C : public UPT_BASE_C
{
public:
    TIMER_C(void);
    TIMER_C(int overTimeCycleNum, BOOL isDefaultTimeOut = true);
    TIMER_C(double overTime, BOOL isDefaultTimeOut = true);
    ~TIMER_C(void);

    void SetOverTime(int overTimeCycleNum);
    void SetOverTime(double overTime);
    void Upt(void);
    void Reset(void);
    void Reset(int overTimeCycleNum);
    void Reset(double overTime);
    void ResetAndAddTime(double addTime);
    void Clear(void);
    void Clear(int leftTimeCycleNum);
    void Clear(double leftTime);
    bool IsTimeOut(void) const;
protected:
private:
    double        overTime_;                   /* 定时器超时时间，为循环周期整倍数时准备，否则近似计算循环次数 */
    int           overTimeCycleNum_;           /* 定时器超时时间对应的循环周期数，优先使用 */
    atomic_int    leftTimeCycleNum_;           /* 多线程访问 *//* 离定时器超时剩余的循环周期数 */
};

/**************************************************************************************
功能描述: 周期时长统计
修改记录:
**************************************************************************************/
class CYCLE_LEN_STATIS_C
{
public:
    CYCLE_LEN_STATIS_C(double outputCycle = 60.0 * 5.0, double expectedCycleLen = 0.0, double abnCycleErrRate = 0.1)
    {
        Set(outputCycle, expectedCycleLen, abnCycleErrRate);

        lastCycleTime_ = 0.0;

        ClearStatis();
    }

    void Set(double outputCycle, double expectedCycleLen, double abnCycleErrRate);
    void Add(void);

private:
    double      outputCycle_;         /* 输出统计信息周期时长 */
    double      expectedCycleLen_;    /* 预期周期时长，为0时不统计周期偏差比例 */
    double      abnCycleDiffMax_;     /* 遗产周期误差限值 */

    double      lastCycleTime_;

    double      maxCycleLen_;
    double      minCycleLen_;
    double      totalCycleLen_;
    UINT32      statisCount_;
    double      totalCycleDiff_;
    UINT32      abnCycleCount_;

    void AddStatis(void);
    void ClearStatis(void);
    void OutputStatis(void);
};

/**************************************************************************************
功能描述: 周期控制和统计
修改记录:
**************************************************************************************/
class PERIOD_TIME_STATIS_C
{
public:
    PERIOD_TIME_STATIS_C(const string &strModule, double periodTime = 1.0, double stepSleepTime = 0.005)
    {
        strModule_      = strModule;
        workPeriodTime_ = periodTime;
        logPeriodTime_  = 60.0;
        stepSleepTime_  = stepSleepTime;

        lastLogTime_    = Comm_GetTimeSecRos();
        startWorkTime_  = 0.0;

        ClearStatis();
    }

    void Start(void);
    void Stop(BOOL isSucc);
    void Wait(void);

    BOOL IsWorkPeriodTimeout(void);

private:
    string strModule_;                      /* 统计信息的模块名 */
    double workPeriodTime_;                 /* 周期时长 */
    double logPeriodTime_;                  /* 日志记录周期时长 */
    double stepSleepTime_;                  /* 单次睡眠时长 */

    double lastLogTime_;                    /* 上次日志的时间 */
    double startWorkTime_;

    /* 统计信息 */
    UINT32 periodCount_;
    UINT32 periodCountSucc_;
    double succPeriodSpentTimeTotal_;
    double succPeriodSpentTimeMax_;
    double failPeriodSpentTimeMax_;
    double maxStartTimeDiff_;

    void ClearStatis(void);
    void AddStatis(double curTime, BOOL isSucc);
    void OutputStatis(double curTime);
};



#endif

